;//~ ***************************************************************************************
;//~ ***************** 			   			MODULO AGENT					  **************
;//~ ***************************************************************************************

(defmodule AGENT (import MAIN ?ALL) (export ?ALL))

(deftemplate kagent 
	(slot time) (slot step)
	(slot pos-r) (slot pos-c) 
    (slot direction)
)

(deftemplate kagent_cell 
	(slot pos-r) (slot pos-c)
	(slot type (allowed-values urban rural lake hill gate border))
	(slot percepted (allowed-values no water border gate hill urban rural)(default no))
	(slot visited (allowed-values true false)(default false)) ;//~ 	indica se ci sono effettivamente passato sopra
	(slot monitored (allowed-values no other low-water deep-water)(default no))
	(slot utility (default 0))
	(slot informed (allowed-values no ok flood initial-flood severe-flood)(default no))
)

(deftemplate next_cell
	(slot pos-r) (slot pos-c) 
    (slot direction)
    (slot utility (default -99999))
	(slot action)
	(slot safety (allowed-values NA safe unsafe)(default NA))
)

;//~ ; rappresenta la percezione locale (ad ogni passo) dell'agente in termini delle 9 celle che e' in grado
;//~ ; di osservare: ogni campo e' rappresentato da 3 valori: posizione, riga e colonna 
;//~ ; -> es. (local_perc (p 1) (r 5) (c 4)) cioe' cella 1 di riga 5 e colonna 4
(deftemplate local_perc 
	(slot p)
	(slot r)
	(slot c)
	(slot checked (allowed-values yes no) (default no))
)

;//~ template che rappresenta un passo di movimento dell'intero cammino calcolato con A* a profondita' limitata per calcolare l'utilità maggiore
(deftemplate way_point
	(slot way-point-id)
	(slot way-point-r)
	(slot way-point-c)
	(slot way-point-dir)
	(slot way-point-time)
	(slot way-point-steps)
	(slot way-point-utility)
	(slot way-point-inform-cost(default 0))   ;//~ informazione relativa al costo temporale necessario per effettuare una inform qualora fosse necessaria
)
;//~ template che rappresenta un goal temporaneo durante il calcolo di A* a profondità limitata
(deftemplate goal
	(slot goal-id)
	(slot goal-r) (slot goal-c) 
	(slot goal-direction)
	(slot goal-time (default 99999)) (slot goal-steps)
	(slot goal-status (allowed-values NA found unreachable) (default NA))
 	(slot distance (default 99999))       ;//~ distanza di Manhattan calcolata dalla posizione dell'agente al gate
 	(slot goal-utility (default -99999))  ;//~ prima il default era a 0
 	(slot goal-reachable (allowed-values NA yes no) (default NA))
 	(slot goal-inform-cost(default 0))        ;//~ informazione relativa al costo temporale necessario per effettuare eventuali inform sulle celle considerate per arrivare al goal(di percorso e neighbours)
)

;//~ regola che inizializza i contatori rural_number e urban_number a 0 prima che vengano incrementati in fase di creazione delle kagent_cell
(defrule create-counters
	(declare (salience 100))
	(maxduration ?md)
	(initial_agentstatus (pos-r ?r) (pos-c ?c)(direction ?dir))
 =>
	(assert (rural_number 0)
			(urban_number 0)
			(actual_urban 0 0)
			(actual_rural 0 0))
)

(defrule create-kagent-cell-urban
	(declare (salience 51))
	(actual_urban ?aur ?auc)
	(prior_cell (pos-r ?r&:(neq ?r 0)) (pos-c ?c&:(neq ?c 0)) (type urban))
	?nou <- (urban_number ?nu)
	(not(actual_urban ?r ?c))
 =>
	(retract ?nou)
	(assert (kagent_cell (pos-r ?r) (pos-c ?c) (type urban) (utility 15)))
	(assert (urban_number (+ ?nu 1))
			(actual_urban ?r ?c))
)

(defrule create-kagent-cell-rural
	(declare (salience 51))
	(actual_rural ?arr ?arc)
	(prior_cell (pos-r ?r&:(neq ?r 0)) (pos-c ?c&:(neq ?c 0)) (type rural))
	?nor <- (rural_number ?nr)
	(not(actual_rural ?r ?c))
 =>
	(retract ?nor)
	(assert (kagent_cell (pos-r ?r) (pos-c ?c) (type rural) (utility 10)))
	(assert (rural_number (+ ?nr 1))
			(actual_rural ?r ?c))
)

(defrule create-kagent-cell-lake
	(declare (salience 51))
	(prior_cell (pos-r ?r) (pos-c ?c) (type lake))
 =>
	(assert (kagent_cell (pos-r ?r) (pos-c ?c) (type lake) (utility 3)))
)

(defrule create-kagent-cell-gate
	(declare (salience 51))
	(prior_cell (pos-r ?r) (pos-c ?c) (type gate))
 =>
	(assert (kagent_cell (pos-r ?r) (pos-c ?c) (type gate) (utility 1)))
)

(defrule create-kagent-cell-other
	(declare (salience 51))
	(prior_cell (pos-r ?r) (pos-c ?c) (type ?t&:(or (eq ?t border) (eq ?t hill))))
 =>
	(assert (kagent_cell (pos-r ?r) (pos-c ?c) (type ?t)))
)

;//~ ***************************************************************************************
;//~ **************      FIRST STEP: PRIMO PASSO DI USCITA DAL GATE      *******************
;//~ ***************************************************************************************

;//~ regola che implementa la prima azione dell'agente
(defrule  beginagent
	(declare (salience 10))
    (status (step 0))
    (not (exec (step 0)))
    (initial_agentstatus (pos-r ?r) (pos-c ?c) (direction ?d))
    (maxduration ?md)
    (test (or (> ?md 10) (= ?md 10)))
 => 
    (assert 
		(kagent (time 0) (step 0) (pos-r ?r) (pos-c ?c) (direction ?d))
		(first_step)
		(planning) 		  ;//~ indica che siamo in fase di pianificazione
		(current_goal 0)  ;//~ indice del goal-gate su cui dobbiamo fare A* a profondita' limitata
		(gate_counter 0)  ;//~ conta quanti goal-gate sono presenti nella mappa
		(max_distance 99999)
		(min_distance 0)
		(gate_calculated 0)	
		(path_utility 0)
		(inform_cost 0)
		(counter_way_point 0)
		(next_cell_counter 0)
		(informed_rural 0) ;//~ contatore delle celle di tipo rural informate
		(informed_urban 0) ;//~ contatore delle celle di tipo urban informate
	)
)

(defrule first-next-cell-north
	(declare (salience 1))
	(first_step)
	(status (step 0))
	(not (exec (step 0)))
	(kagent (time 0) (step 0) (pos-r ?r) (pos-c ?c) (direction north))
 =>
	(assert (next_cell (pos-r (+ ?r 1)) (pos-c ?c) (action go-forward) (direction north)))
	(assert (current_max_goal_utility (+ ?r 1) ?c north -99999))
)

(defrule first-next-cell-south
	(declare (salience 1))
	(first_step)
	(status (step 0))
	(not (exec (step 0)))
	(kagent (time 0) (step 0) (pos-r ?r) (pos-c ?c) (direction south))
 =>
	(assert (next_cell (pos-r (- ?r 1)) (pos-c ?c) (action go-forward) (direction south)))
	(assert (current_max_goal_utility (- ?r 1) ?c south -99999))
)

(defrule first-next-cell-east
	(declare (salience 1))
	(first_step)
	(status (step 0))
	(not (exec (step 0)))
	(kagent (time 0) (step 0) (pos-r ?r) (pos-c ?c) (direction east))
 =>
	(assert (next_cell (pos-r ?r) (pos-c (+ ?c 1)) (action go-forward) (direction east)))
	(assert (current_max_goal_utility ?r (+ ?c 1) east -99999))
)

(defrule first-next-cell-west
	(declare (salience 1))
	(first_step)
	(status (step 0))
	(not (exec (step 0)))
	(kagent (time 0) (step 0) (pos-r ?r) (pos-c ?c) (direction west))
 =>
	(assert (next_cell (pos-r ?r) (pos-c (- ?c 1)) (action go-forward) (direction west)))
	(assert (current_max_goal_utility ?r (- ?c 1) west -99999))
)

;//~ regola che imposta la next cell durante la fase di first step a safety
(defrule first-step-safety
	(not (planning))
	(maxduration ?md)
	(status (step 0))
	(not (exec (step 0)))
	(kagent (time 0) (step 0))
	(first_step)
	(goal
		(goal-id ?gid)
		(goal-r ?gr) (goal-c ?gc) 
		(goal-direction ?gdir)
		(goal-time ?gt) (goal-steps ?gs)
		(goal-status found)
		(goal-utility ?gu&:(neq ?gu -99999))
		(goal-inform-cost ?infc)
	)
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (action go-forward)(utility ?u)(safety NA))
	(current_max_goal_utility ?r ?c ?dir ?u)
	(test (or(> (- ?md ?gt ?infc 10) 0) (= (- ?md ?gt ?infc 10) 0))) 
=>
	(modify ?nc (safety safe))
)

(defrule first-step
	(not (planning))
	?tfs <- (first_step)
	(status (step 0))
	(not (exec (step 0)))
	(kagent (time 0) (step 0))
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?d) (action go-forward)(safety safe))  ;;condizione da aggiungere 
	(not (kagent_cell (pos-r ?r) (pos-c ?c) (type hill|border)))
 =>
	(assert (exec (action go-forward) (step 0))  )
	(retract ?tfs ?nc)
)

;//~ regola per assegnare il campo distance ai goal/gate
(defrule calculate-distance
	(declare (salience 10))
	(planning)
	(maxduration ?md)
	(initial_agentstatus (pos-r ?ir) (pos-c ?ic))
	?gcalc <- (gate_calculated ?gcl)
	(goal
			(goal-id ?giid)
			(goal-r ?ir) (goal-c ?ic) 
			(distance 99999)
	)
	?go <- (goal
			(goal-id ?gid&:(neq ?gid ?giid))
			(goal-r ?gr) (goal-c ?gc)
			(goal-direction ?gdir)
			(goal-time ?gt) (goal-steps ?gs)
			(distance 99999)
			)			
	
	;//~ esclusione delle next_cell di tipo gate in quanto non è necessario pianificare da questo tipo di celle
	(current_max_goal_utility ?x ?y ?dir ?cmgu)
	(next_cell (pos-r ?x) (pos-c ?y) (direction ?dir))
	(kagent_cell (pos-r ?x) (pos-c ?y)(type ~gate))
	
=>
	(modify ?go (distance (* (+ (abs (- ?x ?gr)) (abs (- ?y ?gc))) 10)))
	(retract ?gcalc)
	(assert (gate_calculated (+ ?gcl 1)))
)


;//~ ***************************************************************************************
;//~ *******                 NO-PLANNING-GATE-NEXT-CELL 						************
;//~ *******  Regole attivate nel caso in cui la next_cell è un gate 			************
;//~ *******  e non avrà bisogno della fase di pianificazione ne tantomeno      ************
;//~ *******  del calcolo utilità (che di default sarà -99999)                  ************
;//~ ***************************************************************************************

(defrule no-planning-gate-next-cell-safe-forward
	(declare (salience 10))
	?pl <- (planning)
	?ch <- (checking)
	(status (step ?i) (time ?t))
	(maxduration ?md)
	(current_max_goal_utility ?x ?y ?dir ?cmgu)
	?nc <- (next_cell (pos-r ?x) (pos-c ?y) (direction ?dir) (action go-forward) (safety NA))
	(kagent_cell (pos-r ?x) (pos-c ?y)(type gate))
	(test (or(> (- ?md ?t 10) 0) (= (- ?md ?t 10) 0)))
=>
	(modify ?nc (utility 0)(safety safe))
	(retract ?pl ?ch)
)

(defrule no-planning-gate-next-cell-safe-left-right
	(declare (salience 10))
	?pl <- (planning)
	?ch <- (checking)
	(status (step ?i) (time ?t))
	(maxduration ?md)
	(current_max_goal_utility ?x ?y ?dir ?cmgu)
	?nc <- (next_cell (pos-r ?x) (pos-c ?y) (direction ?dir) (action go-left|go-right) (safety NA))
	(kagent_cell (pos-r ?x) (pos-c ?y)(type gate))
	(test (or(> (- ?md ?t 15) 0) (= (- ?md ?t 15) 0)))
=>
	(modify ?nc (utility 0)(safety safe))
	(retract ?pl ?ch)
)

(defrule no-planning-gate-next-cell-unsafe-forward
	(declare (salience 10))
	?pl <- (planning)
	?ch <- (checking)
	(status (step ?i) (time ?t))
	(maxduration ?md)
	(current_max_goal_utility ?x ?y ?dir ?cmgu)
	?nc <- (next_cell (pos-r ?x) (pos-c ?y) (direction ?dir) (action go-forward) (safety NA))
	(kagent_cell (pos-r ?x) (pos-c ?y)(type gate))
	(test (< (- ?md ?t 10) 0))
=>
	(modify ?nc (utility 0)(safety unsafe))
	(retract ?pl ?ch)
)

(defrule no-planning-gate-next-cell-unsafe-left-right
	(declare (salience 10))
	?pl <- (planning)
	?ch <- (checking)
	(status (step ?i) (time ?t))
	(maxduration ?md)
	(current_max_goal_utility ?x ?y ?dir ?cmgu)
	?nc <- (next_cell (pos-r ?x) (pos-c ?y) (direction ?dir) (action go-left|go-right) (safety NA))
	(kagent_cell (pos-r ?x) (pos-c ?y)(type gate))
	(test (< (- ?md ?t 15) 0))
=>
	(modify ?nc (utility 0)(safety unsafe))
	(retract ?pl ?ch)
)

;//~ regola che sceglie il gate con massima distanza che non sia il gate di partenza
(defrule choose-max-distance-gate
	(declare (salience 9))
	(planning)
	(goal (goal-id ?gid) (goal-status NA) (distance ?di&:(neq ?di 99999)))
	?maxd <- (max_distance ?max)
	?mind <- (min_distance ?min)
	?c <- (current_goal ?cg)
	(test (> ?di ?min))
	(gate_counter ?gc)
	(gate_calculated ?gcl)
	(test (= (- ?gc 1) ?gcl))
 =>
	(retract ?c ?maxd ?mind)
	(assert (min_distance ?di) (max_distance ?di) (current_goal ?gid) ) 
)

;//~  regola che modifica il campo utility dei way-point già visitati dopo la fase di planning per un determinato goal found
(defrule change-utility-way-point-visited
	(declare (salience 11))
	(not (planning))
	(maxduration ?md)
	?g<-(goal
		(goal-id ?gid)
		(goal-r ?gr) (goal-c ?gc) 
		(goal-direction ?gdir)
		(goal-time ?gt) (goal-steps ?gs)
		(goal-status found)
	)
	(way_point
		(way-point-id ?gid)
		(way-point-r ?r) (way-point-c ?c)
		(way-point-steps ?wpstep1)
		(way-point-utility ?wpu)
	)
	?fwp <- (way_point
		(way-point-id ?gid)
		(way-point-r ?r) (way-point-c ?c)
 		(way-point-steps ?wpstep2&:(neq ?wpstep2 ?wpstep1))
		(way-point-utility ?wpu&:(> ?wpu -3))
	)
=>
	(modify ?fwp (way-point-utility -3))
)

;//~ regola che nella prima fase cambia l'utilità dei way_point nel caso in cui siano dei gate impostandola a 0
(defrule change-utility-way-point-gate
	(declare (salience 11))
	(not (planning))
	(maxduration ?md)
	(kagent_cell (pos-r ?r) (pos-c ?c) (type gate))
	?g<-(goal
		(goal-id ?gid)
		(goal-r ?gr) (goal-c ?gc) 
		(goal-direction ?gdir)
		(goal-time ?gt) (goal-steps ?gs)
		(goal-status found)
	)
	?fwp <- (way_point
		(way-point-id ?gid)
		(way-point-r ?r) (way-point-c ?c)
		(way-point-dir ?dir&:(eq ?dir nil))
		(way-point-time ?t&:(eq ?t nil))
		(way-point-utility 3)
	)
=>
	(modify ?fwp (way-point-utility 0))
)

;//~ regola che setta il costo di inform per ogni way-point corrispondente ad una cella di tipo urban o rural. il costo di inform della cella sarà 1
(defrule set-inform-cost-way-point
	(declare (salience 11))
	(not (planning))
	(maxduration ?md)
	(kagent_cell (pos-r ?r) (pos-c ?c) (type urban|rural))
	?g<-(goal
		(goal-id ?gid)
		(goal-r ?gr) (goal-c ?gc) 
		(goal-direction ?gdir)
		(goal-time ?gt) (goal-steps ?gs)
		(goal-status found)
		(goal-inform-cost 0)
	)
	?fwp <- (way_point
		(way-point-id ?gid)
		(way-point-r ?r) (way-point-c ?c)
		(way-point-utility 10|15) ;//~ in questo modo sarà possibile considerare solo celle urban o rural non ancora informate
		(way-point-inform-cost 0)	
	)
=>
	(modify ?fwp (way-point-inform-cost 1))
)


;//~ setta l'utilità del goal/gate come somma delle utilità dei way_point associati al goal/gate 
;//~ ed anche il costo per informare lungo il percorso che porta al goal
(defrule sum-all-path-utility
	(declare (salience 10))
	(not (planning))
	(maxduration ?md)
	?cw <- (counter_way_point ?currwpid)
	?g<-(goal
		(goal-id ?gid)
		(goal-r ?gr) (goal-c ?gc) 
		(goal-direction ?gdir)
		(goal-time ?gt) (goal-steps ?gs)
		(goal-status found)
	)
	?fwp <- (way_point
		(way-point-id ?gid)
		(way-point-r ?r) (way-point-c ?c)
		(way-point-utility ?wpu)
		(way-point-inform-cost ?wpic)
	)
	?pu <- (path_utility ?u)
	?infc <- (inform_cost ?ic)
=>
	(retract ?pu ?cw ?fwp ?infc)
	(assert
		(path_utility (+ ?wpu ?u))
		(inform_cost (+ ?ic ?wpic))
		(counter_way_point (+ ?currwpid 1))
	)
	(modify ?g (goal-utility (+ ?wpu ?u))
			   (goal-inform-cost (+ ?ic ?wpic))
	)
)

;//~ regola che permette di resettare i fatti utilizzati durante la somma dei way-point
(defrule reset-facts-utility-sum
	(declare (salience 9))
	(not (planning))
	?cw <- (counter_way_point ?currwpid)
	?pu <- (path_utility ?u)
	?ic <- (inform_cost ?infc)
	(goal
		(goal-id ?gid)
		(goal-r ?gr) (goal-c ?gc) 
		(goal-direction ?gdir)
		(goal-status found)
	)
	(test (neq ?currwpid 0 ))
=>
	(retract ?cw ?pu)
	(assert
		(path_utility 0)
		(inform_cost 0)
		(counter_way_point 0)
	)
)

;//~ sceglie il gate con massima distanza dopo la fase di planning
(defrule choose-max-distance-gate-after-planning
	(declare (salience 9))
	(not(planning))
	(goal (goal-id ?gid) (goal-status NA) (distance ?di&:(neq ?di 99999)))
	?maxd <- (max_distance ?max)
	?mind <- (min_distance ?min)
	?c <- (current_goal ?cg)
	(test (> ?di ?min))
	(gate_counter ?gc)
	(gate_calculated ?gcl)
	(test (= (- ?gc 1) ?gcl))
 =>
	(retract ?c ?maxd ?mind)
	(assert (min_distance ?di) (max_distance ?di) (current_goal ?gid) (planning)) 
)

;//~ regola che sceglie il gate di partenza
(defrule choose-start-gate
	(declare (salience 9))
	(planning)
	(goal (goal-id ?gid) (goal-status NA) (distance ?di&:(eq ?di 99999)))
	?maxd <- (max_distance ?max)
	?mind <- (min_distance ?min)
	?c <- (current_goal ?cg)
	(test (> ?di ?min))
	(gate_counter ?gc)
	(gate_calculated ?gcalc)
	(test (= (- ?gc ?gcalc) 1))
 =>
	(retract ?c ?maxd ?mind)
	(assert (min_distance ?di) (max_distance ?di) (current_goal ?gid)) 
)


;//~ ***************************************************************************************
;//~ ******************             REGOLE DI FIND-GATES                     ***************
;//~ ***************************************************************************************

(defrule find-gates-south
	(declare (salience 11))
	(first_step)
	(kagent_cell (pos-r 1) (pos-c ?c) (type gate))
	(kagent_cell (pos-r 1) (pos-c =(- ?c 1)) (type border|gate))
	(kagent_cell (pos-r 1) (pos-c =(+ ?c 1)) (type border|gate))
	?p <- (gate_counter ?pc)
	(not (goal (goal-r 1) (goal-c ?c) (goal-direction south)))
	(not (kagent_cell (pos-r 2) (pos-c ?c) (type hill) ))  ;reasoning geometrico
	(not (and(kagent_cell (pos-r 3) (pos-c ?c) (type hill)) (kagent_cell (pos-r 2) (pos-c =(- ?c 1)) (type hill|border|gate)) (kagent_cell (pos-r 2) (pos-c =(+ ?c 1)) (type hill|border|gate)) ))  ;reasoning geometrico
 =>
	(assert 
		(goal
			(goal-id ?pc)
			(goal-r 1) (goal-c ?c)
			(goal-direction south)
		)
		(gate_counter (+ ?pc 1))
		
	)
	(retract ?p)
)

(defrule find-gates-north
	(declare (salience 11))
	(first_step)
	(kagent_cell (pos-r ?r&:(neq ?r 1)) (pos-c ?c) (type gate))
	(kagent_cell (pos-r ?r&:(neq ?r 1)) (pos-c =(- ?c 1)) (type border|gate))
	(kagent_cell (pos-r ?r&:(neq ?r 1)) (pos-c =(+ ?c 1)) (type border|gate))
	?p <- (gate_counter ?pc)
	(not (goal (goal-r ?r) (goal-c ?c) (goal-direction north)))
	(not (kagent_cell (pos-r =(- ?r 1)) (pos-c ?c) (type hill) )) ;reasoning geometrico
	(not (and(kagent_cell (pos-r =(- ?r 2)) (pos-c ?c) (type hill)) (kagent_cell (pos-r =(- ?r 1)) (pos-c =(- ?c 1)) (type hill|border|gate)) (kagent_cell (pos-r =(- ?r 1)) (pos-c =(+ ?c 1)) (type hill|border|gate)) ))  ;reasoning geometrico
 =>
	(assert 
		(goal
			(goal-id ?pc)
			(goal-r ?r) (goal-c ?c)
			(goal-direction north)
		)
		(gate_counter (+ ?pc 1))
	)
	(retract ?p)
)

(defrule find-gates-west
	(declare (salience 11))
	(first_step)
	(kagent_cell (pos-r ?r) (pos-c 1) (type gate))
	(kagent_cell (pos-r =(- ?r 1)) (pos-c 1) (type border|gate))
	(kagent_cell (pos-r =(+ ?r 1)) (pos-c 1) (type border|gate))
	?p <- (gate_counter ?pc)
	(not (goal (goal-r ?r) (goal-c 1) (goal-direction west)))
	(not (kagent_cell (pos-r ?r) (pos-c 2) (type hill) )) ;reasoning geometrico
	(not (and(kagent_cell (pos-r ?r ) (pos-c 3) (type hill)) (kagent_cell (pos-r =(- ?r 1)) (pos-c 2) (type hill|border|gate)) (kagent_cell (pos-r =(+ ?r 1)) (pos-c 2) (type hill|border|gate)) ))  ;reasoning geometrico
 =>
	(assert 
		(goal
			(goal-id ?pc)
			(goal-r ?r) (goal-c 1)
			(goal-direction west)
		)
		(gate_counter (+ ?pc 1))
	)
	(retract ?p)
)

(defrule find-gates-east
	(declare (salience 11))
	(first_step)
	(kagent_cell (pos-r ?r) (pos-c ?c&:(neq ?c 1)) (type gate))
	(kagent_cell (pos-r =(- ?r 1)) (pos-c ?c&:(neq ?c 1)) (type border|gate))
	(kagent_cell (pos-r =(+ ?r 1)) (pos-c ?c&:(neq ?c 1)) (type border|gate))
	?p <- (gate_counter ?pc)
	(not (goal (goal-r ?r) (goal-c ?c) (goal-direction east)))
	(not (kagent_cell (pos-r ?r) (pos-c =(- ?c 1)) (type hill) )) ;reasoning geometrico
	(not (and(kagent_cell (pos-r ?r) (pos-c =(- ?c 2)) (type hill)) (kagent_cell (pos-r =(- ?r 1)) (pos-c =(- ?c 1)) (type hill|border|gate)) (kagent_cell (pos-r =(+ ?r 1)) (pos-c =(- ?c 1)) (type hill|border|gate)) ))  ;reasoning geometrico
 =>
	(assert 
		(goal
			(goal-id ?pc)
			(goal-r ?r) (goal-c ?c)
			(goal-direction east)
		)
		(gate_counter (+ ?pc 1))
	)
	(retract ?p)
)

;//~ *******************************************************************************************************************************
;//~ ******** regole che permettono di impostare un goal a reachable o unreachable in base al controllo sul tempo ******************
;//~ *******************************************************************************************************************************

(defrule set-goal-reachable-forward
	(declare (salience 4))
	(status (step ?i) (time ?t))
	(checking)
	(not(first_step))
	(not (planning))
	(current_max_goal_utility ?r ?c ?dir ?gu)
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (action go-forward) (safety NA))
	(kagent_cell (pos-r ?r) (pos-c ?c)(type ~gate))
	?g<-(goal
		(goal-id ?gid)
		(goal-time ?gt)
		(goal-status found)
		(goal-reachable NA)
		(goal-inform-cost ?infc)
	)
	(maxduration ?md)
	(test (or(> (- ?md ?t ?gt ?infc 10) 0) (= (- ?md ?t ?gt ?infc 10) 0)))
 =>
	(modify ?g (goal-reachable yes))
)

(defrule set-goal-reachable-left-right
	(declare (salience 4))
	(status (step ?i) (time ?t))
	(checking)
	(not(first_step))
	(not (planning))
	(current_max_goal_utility ?r ?c ?dir ?gu)
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (action go-left|go-right) (safety NA))
	(kagent_cell (pos-r ?r) (pos-c ?c)(type ~gate))
	?g<-(goal
		(goal-id ?gid)
		(goal-time ?gt)
		(goal-status found)
		(goal-reachable NA)
		(goal-inform-cost ?infc)
	)
	(maxduration ?md)
	(test (or(> (- ?md ?t ?gt ?infc 15) 0) (= (- ?md ?t ?gt ?infc 15) 0)))
 =>
	(modify ?g (goal-reachable yes))
)

(defrule set-goal-unreachable-forward
	(declare (salience 4))
	(status (step ?i) (time ?t))
	(checking)
	(not(first_step))
	(not (planning))
	(current_max_goal_utility ?r ?c ?dir ?gu)
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (action go-forward) (safety NA))
	(kagent_cell (pos-r ?r) (pos-c ?c)(type ~gate))
	?g<-(goal
		(goal-id ?gid)
		(goal-time ?gt)
		(goal-status found)
		(goal-reachable NA)
		(goal-inform-cost ?infc)
	)
	(maxduration ?md)
	(test (< (- ?md ?t ?gt ?infc 10) 0))
 =>
	(modify ?g (goal-reachable no))
)

(defrule set-goal-unreachable-left-right
	(declare (salience 4))
	(status (step ?i) (time ?t))
	(checking)
	(not(first_step))
	(not (planning))
	(current_max_goal_utility ?r ?c ?dir ?gu)
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (action go-left|go-right) (safety NA))
	(kagent_cell (pos-r ?r) (pos-c ?c)(type ~gate))
	?g<-(goal
		(goal-id ?gid)
		(goal-time ?gt)
		(goal-status found)
		(goal-reachable NA)
		(goal-inform-cost ?infc)
	)
	(maxduration ?md)
	(test (< (- ?md ?t ?gt ?infc 15) 0))
 =>
	(modify ?g (goal-reachable no))
)

;//~ assegna l'utilità massima alla next_cell selezionandola tra le utilità dei goal found  
(defrule max-goal-reachable-utility
	(declare (salience 3))
	(checking)
	(not(first_step))
	(not (planning))
	(status (step ?i) (time ?t))
	(maxduration ?md)
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (safety NA))
	(kagent_cell (pos-r ?r) (pos-c ?c)(type ~gate))
	?cmg <- (current_max_goal_utility ?r ?c ?dir ?cmgu)
	?g<-(goal
		(goal-id ?gid)
		(goal-r ?gr) (goal-c ?gc) 
		(goal-direction ?gdir)
		(goal-time ?gt) (goal-steps ?gs)
		(goal-status found)
		(goal-utility ?gu&:(neq ?gu -99999))
		(goal-reachable yes)
		(goal-inform-cost ?infc)
	)
	(test (> ?gu ?cmgu))
	(test (> (- ?md  ?t ?gt ?infc) 0))
=>
	(retract ?cmg)
	(assert (current_max_goal_utility ?r ?c ?dir ?gu))
	(modify ?nc (utility ?gu))
)

;//~ *******************************************************************************************************************************
;//~ *****      Regole che permettono di impostare una next_cell a safe o unsafe in base al calcolo sul tempo             **********
;//~ *******************************************************************************************************************************

(defrule next-cell-safe-forward
	(declare (salience 2))
	(status (step ?i) (time ?t))
	(checking)
	(not(first_step))
	(not (planning))
	(current_max_goal_utility ?r ?c ?dir ?gu&:(neq ?gu -99999))
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (action go-forward) (safety NA))
	(kagent_cell (pos-r ?r) (pos-c ?c)(type ~gate))
	(goal (goal-id ?gid) (goal-time ?gt) (goal-status found)(goal-reachable yes)(goal-inform-cost ?infc))
	(maxduration ?md)
	(test (or(> (- ?md ?t ?gt ?infc 10) 0) (= (- ?md ?t ?gt ?infc 10) 0)))
 =>
	(modify ?nc (safety safe))
)

(defrule next-cell-safe-left-right
	(declare (salience 2))
	(status (step ?i) (time ?t))
	(checking)
	(not(first_step))
	(not (planning))
	(current_max_goal_utility ?r ?c ?dir ?gu&:(neq ?gu -99999))
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (action go-left|go-right) (safety NA))
	(kagent_cell (pos-r ?r) (pos-c ?c)(type ~gate))
	(goal (goal-id ?gid) (goal-time ?gt) (goal-status found)(goal-reachable yes)(goal-inform-cost ?infc))
	(maxduration ?md)
	(test (or(> (- ?md ?t ?gt ?infc 15) 0) (= (- ?md ?t ?gt ?infc 15) 0)))
 =>
	(modify ?nc (safety safe))
)

(defrule next-cell-unsafe-forward
	(declare (salience 2))
	(status (step ?i) (time ?t))
	(checking)
	(not(first_step))
	(not (planning))
	(current_max_goal_utility ?r ?c ?dir ?gu&:(neq ?gu -99999))
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (action go-forward) (safety NA))
	(kagent_cell (pos-r ?r) (pos-c ?c)(type ~gate))
	(goal (goal-id ?gid) (goal-time ?gt) (goal-status found)(goal-reachable no)(goal-inform-cost ?infc))
	(maxduration ?md)
	(test (< (- ?md ?t ?gt ?infc 10) 0))
 =>
	(modify ?nc (safety unsafe))
)

(defrule next-cell-unsafe-left-right
	(declare (salience 2))
	(status (step ?i) (time ?t))
	(checking)
	(not(first_step))
	(not (planning))
	(current_max_goal_utility ?r ?c ?dir ?gu&:(neq ?gu -99999))
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (action go-left|go-right) (safety NA))
	(kagent_cell (pos-r ?r) (pos-c ?c)(type ~gate))
	(goal (goal-id ?gid) (goal-time ?gt) (goal-status found)(goal-reachable no)(goal-inform-cost ?infc))
	(maxduration ?md)
	(test (< (- ?md ?t ?gt ?infc 15) 0))
 =>
	(modify ?nc (safety unsafe))
)

;//~ caso in cui da una determinata next_cell tutti i goal found non sono raggiungibili(quindi non unreachable ma semplicemente fisicamente irragiungibili). 
;//~ La next_cell verrà settata unsafe e successivamente cancellata dalle regole di cancellazione.
;//~ Attenzione non è una copia della regola sottostante ignore-all-unreachable; fanno cose diverse.
(defrule ignore-next-cell-goal-reachable-no
	(declare (salience 1))
	(not(first_step))
	?ch <- (checking)
	(not (planning))
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (utility -99999) (safety NA))
	(not(kagent_cell (pos-r ?r) (pos-c ?c) (type gate)))
	(current_max_goal_utility ?r ?c ?dir -99999)
	(goal
		(goal-id ?gid)
		(goal-status found)
		(goal-reachable no)
	)
=>
	(modify ?nc (safety unsafe))
	(retract ?ch)
)

;//~ ignora tutti i goal unreachable in quanto da quella next_cell fisicamente i goal non sono raggiungibili e salta alle regole di cancellazione
(defrule ignore-all-unreachable
	(declare (salience 1))
	?ch <- (checking)
	(not(first_step))
	(not (planning))
	?nc <- (next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (utility -99999) (safety NA))
	(not(kagent_cell (pos-r ?r) (pos-c ?c) (type gate))) ;; in alternativa (kagent_cell (pos-r ?r) (pos-c ?c) (type ~gate)) le due scritture sono equivalenti?
	(current_max_goal_utility ?r ?c ?dir -99999)
	(next_cell_counter ?ncc)
	(goal
		(goal-id ?gid)
		(goal-status unreachable)
		(goal-utility -99999)
	)
	;//~ Aggiunto questo test perchè la regola si dovrà attivare se e solo se esisterà una next_cell alternativa da cui muoversi
	(test(> ?ncc 1))     
=>
	(modify ?nc (safety unsafe))
	(retract ?ch)
)

;//~ regola che si attiva solo se sono stati scartati tutti gli altri percorsi e la next_cell coincide con un gate
(defrule close-to-gate
	(declare (salience 16))
	(not(checking))
	(not(first_step))
	(not (planning))
	(next_cell (pos-r ?r1) (pos-c ?c1) (direction ?dir1) (utility -99999) (safety NA))
	(kagent_cell (pos-r ?r1) (pos-c ?c1) (type gate))
	(current_max_goal_utility ?r1 ?c1 ?dir1 -99999)
	(goal
		(goal-id ?gid)
		(goal-status NA)
		(distance 99999)
	)
	(next_cell_counter ?ncc)
;//~ Aggiunto controllo sul numero di next_cell = 1 in modo tale che si attivi la ready-to-movement che provvederà al movimento
	(test (= ?ncc 1))     
=>
	(assert (movement)
			(next_cell_counter 0)
	)
)

(defrule after-set-goal-utility
	(declare (salience 1))
	?ch <- (checking)
	(not(first_step))
	(not (planning))
	(next_cell (utility ?u))
	(goal
		(goal-status found)
		(goal-utility ?gu)
	)
	(test (= ?gu ?u))
=>
	(retract ?ch)
)

;//~ regola che resetta i parametri dei goal ai valori di default
(defrule reset-goal
	(declare (salience 11))
	(not (checking))
	(not (planning))
	(not (first_step))
	?g <- (goal
			(goal-id ?gid)
			(goal-r ?gr) (goal-c ?gc) 
			(goal-status ?gs&:(neq ?gs NA))
			(distance ?di)
		)
 =>
	(modify ?g 
			(goal-time 99999) (goal-steps nil)
			(goal-status NA)
			(distance 99999)
			(goal-utility -99999)
			(goal-reachable NA)
			(goal-inform-cost 0)
	)
)

;//~ regola che sceglie la next_cell con utilità maggiore e setta a -999990 l'utilità delle altre
(defrule choose-movement
	(declare (salience 11))
	(not (checking))
	(not (planning))
	(not (first_step))
	(next_cell
		(pos-r ?r1) (pos-c ?c1) 
		(direction ?dir1)
		(utility ?u1)
		(action ?a1)
		(safety safe)
	)
	?nc2 <- (next_cell
		(pos-r ?r2) (pos-c ?c2) 
		(direction ?dir2)
		(utility ?u2&:(neq ?u2 -999990)) ;//~ il valore -999990 viene utilizzato per scartare la next_cell con utilità minore
		(action ?a2)
		(safety safe)
	)
	(test (neq (str-cat ?r1 ?c1) (str-cat ?r2 ?c2)))
	(test (or(> ?u1 ?u2) (= ?u1 ?u2)))
=>
	(modify ?nc2 (utility -999990) )
)

(defrule reset-counters
	(declare (salience 11))
	(not (checking))
	(not (planning))
	(not (first_step))
	?gcc <- (gate_calculated ?)
	?cg <- (current_goal ?)
	?cw <- (counter_way_point ?)
	?pu <- (path_utility ?)
	?cmg <- (current_max_goal_utility $?)
 =>
	(retract ?gcc ?cg ?cw ?pu ?cmg)
	(assert
		(gate_calculated 0)
		(current_goal 0)
		(counter_way_point 0)
		(path_utility 0)
		(checking)
	)
)

;//~ regola che permette la rimozione delle next_cell scartate in base al confronto effettuato tra next_cell safe dalla regola choose-movement
(defrule remove-next-cell-safe
	(declare (salience 14))
	(not(checking))
	(not (planning))
	(not (first_step))
	?ncounter <- (next_cell_counter ?ncc)
	(status (step ?i))
	?nc <- (next_cell (utility -999990) (safety safe))
=>
	(retract ?nc ?ncounter)
	(assert (next_cell_counter (- ?ncc 1)))
)

;//~ regola che permette la rimozione delle next_cell impostate ad unsafe in base alle regole next-cell-unsafe-....
(defrule remove-next-cell-unsafe
	(declare (salience 14))
	(not(checking))
	(not (planning))
	(not (first_step))
	?ncounter <- (next_cell_counter ?ncc)
	(status (step ?i))
	?nc <- (next_cell (utility ?u&:(neq ?u -999990)) (safety unsafe))
=>
	(retract ?nc ?ncounter)
	(assert (next_cell_counter (- ?ncc 1)))
)

;//~ regola che permette il movimento solo se ci sarà una sola next_cell con valore di utilità diverso da quello di default
(defrule ready-to-movement
	(declare (salience 14))
	(not(checking))
	(not (planning))
	(not (first_step))
	(status (step ?i))
	?nc <- (next_cell_counter ?ncc)
	(next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (utility ?u&:(neq ?u -99999))(safety safe))
	(test (= ?ncc 1))
=>
	(retract ?nc)
	(assert (movement)
			(next_cell_counter 0)
	)
)

(defrule exec-act
	(declare (salience 14))
	(status (step ?i))
    (exec (step ?i))
 => 
	(focus MAIN)
)

;//~ ********************************************************************************************************************************************
;//~ *******************************                    PARTE DI PERC-AGENT                ******************************************************
;//~ ********************************************************************************************************************************************

(defrule perc-agent-north
	(declare (salience 16))
	(status (step ?i))
	?ka <- (kagent (step =(- ?i 1)))
	?pv <- (perc-vision
		(time ?t) (step ?i)
		(pos-r ?r) (pos-c ?c)
		(direction north)
		(perc1 ?p1)(perc2 ?p2)(perc3 ?p3)
		(perc4 ?p4)(perc5 ?p5)(perc6 ?p6)
		(perc7 ?p7)(perc8 ?p8)(perc9 ?p9)
	)
	?f1	<- (kagent_cell (pos-r =(+ ?r 1)) (pos-c =(- ?c 1)))
	?f2 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c ?c))
	?f3 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c =(+ ?c 1)))
	?f4 <- (kagent_cell (pos-r ?r) (pos-c =(- ?c 1)))
	?f5 <- (kagent_cell (pos-r ?r) (pos-c ?c))
	?f6 <- (kagent_cell (pos-r ?r) (pos-c =(+ ?c 1)))
	?f7 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c =(- ?c 1)))
	?f8 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c ?c))
	?f9 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c =(+ ?c 1)))
 =>
	(modify ?f1 (percepted ?p1))(modify ?f2 (percepted ?p2))(modify ?f3 (percepted ?p3))
	(modify ?f4 (percepted ?p4))(modify ?f5 (percepted ?p5) (visited true))(modify ?f6 (percepted ?p6))
	(modify ?f7 (percepted ?p7))(modify ?f8 (percepted ?p8))(modify ?f9 (percepted ?p9))
	(modify ?ka (time ?t) (step ?i) (pos-r ?r) (pos-c ?c) (direction north))
	(assert 
		(local_perc (p 1) (r =(+ ?r 1)) (c =(- ?c 1)))
		(local_perc (p 2) (r =(+ ?r 1)) (c ?c))
		(local_perc (p 3) (r =(+ ?r 1)) (c =(+ ?c 1)))
		(local_perc (p 4) (r ?r) (c =(- ?c 1)))
		(local_perc (p 5) (r ?r) (c ?c))
		(local_perc (p 6) (r ?r) (c =(+ ?c 1)))
		(local_perc (p 7) (r =(- ?r 1)) (c =(- ?c 1)))
		(local_perc (p 8) (r =(- ?r 1)) (c ?c))
		(local_perc (p 9) (r =(- ?r 1)) (c =(+ ?c 1)))
	)
	(retract ?pv)
)

(defrule perc-agent-south
	(declare (salience 16))
	(status (step ?i))
	?ka <- (kagent (step =(- ?i 1)))
	?pv <- (perc-vision
		(time ?t) (step ?i)
		(pos-r ?r) (pos-c ?c)
		(direction south)
		(perc1 ?p1)(perc2 ?p2)(perc3 ?p3)
		(perc4 ?p4)(perc5 ?p5)(perc6 ?p6)
		(perc7 ?p7)(perc8 ?p8)(perc9 ?p9)
	)
	?f1 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c =(+ ?c 1)))
	?f2 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c ?c))
    ?f3 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c =(- ?c 1)))
    ?f4 <- (kagent_cell (pos-r ?r) (pos-c =(+ ?c 1)))
    ?f5 <- (kagent_cell (pos-r ?r) (pos-c ?c))
    ?f6 <- (kagent_cell (pos-r ?r) (pos-c =(- ?c 1)))
    ?f7 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c =(+ ?c 1)))
    ?f8 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c ?c))
    ?f9 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c =(- ?c 1)))
 =>
	(modify ?f1 (percepted ?p1))(modify ?f2 (percepted ?p2))(modify ?f3 (percepted ?p3))
	(modify ?f4 (percepted ?p4))(modify ?f5 (percepted ?p5) (visited true))(modify ?f6 (percepted ?p6))
	(modify ?f7 (percepted ?p7))(modify ?f8 (percepted ?p8))(modify ?f9 (percepted ?p9))
	(modify ?ka (time ?t) (step ?i) (pos-r ?r) (pos-c ?c) (direction south))
	(assert 
		(local_perc (p 1) (r =(- ?r 1)) (c =(+ ?c 1)))
		(local_perc (p 2) (r =(- ?r 1)) (c ?c))
		(local_perc (p 3) (r =(- ?r 1)) (c =(- ?c 1)))
		(local_perc (p 4) (r ?r) (c =(+ ?c 1)))
		(local_perc (p 5) (r ?r) (c ?c))
		(local_perc (p 6) (r ?r) (c =(- ?c 1)))
		(local_perc (p 7) (r =(+ ?r 1)) (c =(+ ?c 1)))
		(local_perc (p 8) (r =(+ ?r 1)) (c ?c))
		(local_perc (p 9) (r =(+ ?r 1)) (c =(- ?c 1)))
	)
	(retract ?pv)	
)

(defrule perc-agent-east
	(declare (salience 16))
	(status (step ?i))
	?ka <- (kagent (step =(- ?i 1)))
	?pv <- (perc-vision
		(time ?t) (step ?i)
		(pos-r ?r) (pos-c ?c)
		(direction east)
		(perc1 ?p1)(perc2 ?p2)(perc3 ?p3)
		(perc4 ?p4)(perc5 ?p5)(perc6 ?p6)
		(perc7 ?p7)(perc8 ?p8)(perc9 ?p9)
	)
	?f1 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c =(+ ?c 1)))
	?f2 <- (kagent_cell (pos-r ?r) (pos-c =(+ ?c 1)))
    ?f3 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c =(+ ?c 1)))
    ?f4 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c ?c))
    ?f5 <- (kagent_cell (pos-r ?r) (pos-c ?c))
    ?f6 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c ?c))
    ?f7 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c =(- ?c 1)))
    ?f8 <- (kagent_cell (pos-r ?r) (pos-c =(- ?c 1)))
    ?f9 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c =(- ?c 1)))
 =>
	(modify ?f1 (percepted ?p1))(modify ?f2 (percepted ?p2))(modify ?f3 (percepted ?p3))
	(modify ?f4 (percepted ?p4))(modify ?f5 (percepted ?p5) (visited true))(modify ?f6 (percepted ?p6))
	(modify ?f7 (percepted ?p7))(modify ?f8 (percepted ?p8))(modify ?f9 (percepted ?p9))
	(modify ?ka (time ?t) (step ?i) (pos-r ?r) (pos-c ?c) (direction east))
	(assert 
		(local_perc (p 1) (r =(+ ?r 1)) (c =(+ ?c 1)))
		(local_perc (p 2) (r ?r) (c =(+ ?c 1)))
		(local_perc (p 3) (r =(- ?r 1)) (c =(+ ?c 1)))
		(local_perc (p 4) (r =(+ ?r 1)) (c ?c))
		(local_perc (p 5) (r ?r) (c ?c))
		(local_perc (p 6) (r =(- ?r 1)) (c ?c))
		(local_perc (p 7) (r =(+ ?r 1)) (c =(- ?c 1)))
		(local_perc (p 8) (r ?r) (c =(- ?c 1)))
		(local_perc (p 9) (r =(- ?r 1)) (c =(- ?c 1)))
	)
	(retract ?pv)	
)

(defrule perc-agent-west
	(declare (salience 16))
	(status (step ?i))
	?ka <- (kagent (step =(- ?i 1)))
	?pv <- (perc-vision
		(time ?t) (step ?i)
		(pos-r ?r) (pos-c ?c)
		(direction west)
		(perc1 ?p1)(perc2 ?p2)(perc3 ?p3)
		(perc4 ?p4)(perc5 ?p5)(perc6 ?p6)
		(perc7 ?p7)(perc8 ?p8)(perc9 ?p9)
	)
	?f1 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c =(- ?c 1)))
	?f2 <- (kagent_cell (pos-r ?r) (pos-c =(- ?c 1)))
    ?f3 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c =(- ?c 1)))
    ?f4 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c ?c))
    ?f5 <- (kagent_cell (pos-r ?r) (pos-c ?c))
    ?f6 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c ?c))
    ?f7 <- (kagent_cell (pos-r =(- ?r 1)) (pos-c =(+ ?c 1)))
    ?f8 <- (kagent_cell (pos-r ?r) (pos-c =(+ ?c 1)))
    ?f9 <- (kagent_cell (pos-r =(+ ?r 1)) (pos-c =(+ ?c 1)))
 =>
	(modify ?f1 (percepted ?p1))(modify ?f2 (percepted ?p2))(modify ?f3 (percepted ?p3))
	(modify ?f4 (percepted ?p4))(modify ?f5 (percepted ?p5) (visited true))(modify ?f6 (percepted ?p6))
	(modify ?f7 (percepted ?p7))(modify ?f8 (percepted ?p8))(modify ?f9 (percepted ?p9))
	(modify ?ka (time ?t) (step ?i) (pos-r ?r) (pos-c ?c) (direction west))
	(assert 
		(local_perc (p 1) (r =(- ?r 1)) (c =(- ?c 1)))
		(local_perc (p 2) (r ?r) (c =(- ?c 1)))
		(local_perc (p 3) (r =(+ ?r 1)) (c =(- ?c 1)))
		(local_perc (p 4) (r =(- ?r 1)) (c ?c))
		(local_perc (p 5) (r ?r) (c ?c))
		(local_perc (p 6) (r =(+ ?r 1)) (c ?c))
		(local_perc (p 7) (r =(- ?r 1)) (c =(+ ?c 1)))
		(local_perc (p 8) (r ?r) (c =(+ ?c 1)))
		(local_perc (p 9) (r =(+ ?r 1)) (c =(+ ?c 1)))
	)
	(retract ?pv)
)

(defrule delete-redundant-local-perc
	(declare (salience 15))
	(not(checking))
	(not (planning))
	(status (step ?i) (time ?t))
	(local_perc (p ?p) (r ?r) (c ?c) (checked yes))
	?lp <- (local_perc (p ?p) (r ?r) (c ?c) (checked no))
 =>
	(retract ?lp)
)

;//~ ********************************************************************************************************************************************
;//~ *******************************                    PARTE DI PERC-MONITOR               *****************************************************
;//~ ********************************************************************************************************************************************

(defrule perc-agent-monitored
	(declare (salience 15))
	?pm <- (perc-monitor
		(time ?t) (step ?i)
		(pos-r ?r) (pos-c ?c)
		(perc ?p)
	)
	?f <- (kagent_cell (pos-r ?r) (pos-c ?c))
 =>
	(modify ?f (monitored ?p))
	(retract ?pm)
)

;//~ ********************************************************************************************************************************************
;//~ *******************************                    PARTE DI INFORM                    ******************************************************
;//~ ********************************************************************************************************************************************

;//~  inform di severe-flood su celle di tipo urban o rural
(defrule inform-severe-flood
	(declare (salience 14))
	(checking)
	(not (planning))
	(status (step ?i) (time ?t))
	(local_perc (r ?r) (c ?c))
	?ka <- (kagent_cell (pos-r ?r) (pos-c ?c) (type urban|rural) (percepted water) (monitored deep-water) (informed flood|no))
	(maxduration ?md)
;//~ controllo già effettuato nell'inform-cost
;//~ 	(goal (goal-time ?rgt))
;//~ 	(test (> (- ?md ?t ?rgt 1) 0))
 =>
	(assert (exec (action inform) (param1 ?r) (param2 ?c) (param3 severe-flood) (step ?i)))
	(modify ?ka (informed severe-flood))
)

;//~  inform di initial-flood su celle di tipo urban o rural
(defrule inform-initial-flood
	(declare (salience 14))
	(checking)
	(not (planning))
	(status (step ?i) (time ?t))
	(local_perc (r ?r) (c ?c))
	?ka <- (kagent_cell (pos-r ?r) (pos-c ?c) (type urban|rural) (percepted water) (monitored low-water) (informed flood|no))
	(maxduration ?md)
;//~ controllo già effettuato nell'inform-cost
;//~ 	(goal (goal-time ?rgt))
;//~ 	(test (> (- ?md ?t ?rgt 1) 0))
 =>
	(assert (exec (action inform) (param1 ?r) (param2 ?c) (param3 initial-flood) (step ?i)))
	(modify ?ka (informed initial-flood))
)

;//~ Le regole di inform-water e di inform-ok sono state duplicate per poter gestire i contatori 
;//~ che tengono il conto delle celle urban/rural informate

;//~  inform di water su celle di tipo urban
(defrule inform-urban-water
	(declare (salience 13))
	(checking)
	(not (planning))
	(status (step ?i) (time ?t))
	(local_perc (r ?r) (c ?c))
	?ka <- (kagent_cell (pos-r ?r) (pos-c ?c) (type urban) (percepted water) (monitored no) (informed no))
	(maxduration ?md)
	?iurb <- (informed_urban ?infurb)
;//~ controllo già effettuato nell'inform-cost
;//~ 	(goal (goal-time ?rgt))
;//~ 	(test (> (- ?md ?t ?rgt 1) 0))
 =>
	(assert (exec (action inform) (param1 ?r) (param2 ?c) (param3 flood) (step ?i)))
	(assert (informed_urban (+ ?infurb 1)))
	(modify ?ka (informed flood))
)

;//~  inform di water su celle di tipo rural
(defrule inform-rural-water
	(declare (salience 13))
	(checking)
	(not (planning))
	(status (step ?i) (time ?t))
	(local_perc (r ?r) (c ?c))
	?ka <- (kagent_cell (pos-r ?r) (pos-c ?c) (type rural) (percepted water) (monitored no) (informed no))
	(maxduration ?md)
	?irur <- (informed_rural ?infrur)
;//~ controllo già effettuato nell'inform-cost
;//~ 	(goal (goal-time ?rgt))
;//~ 	(test (> (- ?md ?t ?rgt 1) 0))
 =>
	(assert (exec (action inform) (param1 ?r) (param2 ?c) (param3 flood) (step ?i)))
	(assert (informed_rural (+ ?infrur 1)))
	(modify ?ka (informed flood))
)

;//~  inform di ok su celle di tipo urban
(defrule inform-urban-ok
	(declare (salience 12))
	(checking)
	(not (planning))
	(status (step ?i) (time ?t))
	(local_perc (r ?r) (c ?c))
	?ka <- (kagent_cell (pos-r ?r) (pos-c ?c) (type urban) (percepted urban|rural) (monitored no) (informed no))
	(maxduration ?md)
	?iurb <- (informed_urban ?infurb)
;//~ controllo già effettuato nell'inform-cost
;//~ 	(goal (goal-time ?rgt))
;//~ 	(test (> (- ?md ?t ?rgt 1) 0))
 =>
	(assert (exec (action inform) (param1 ?r) (param2 ?c) (param3 ok) (step ?i)))
	(assert (informed_urban (+ ?infurb 1)))
	(modify ?ka (informed ok))
)

;//~  inform di ok su celle di tipo rural
(defrule inform-rural-ok
	(declare (salience 12))
	(checking)
	(not (planning))
	(status (step ?i) (time ?t))
	(local_perc (r ?r) (c ?c))
	?ka <- (kagent_cell (pos-r ?r) (pos-c ?c) (type rural) (percepted urban|rural) (monitored no) (informed no))
	(maxduration ?md)
	?irur <- (informed_rural ?infrur)
;//~ controllo già effettuato nell'inform-cost
;//~ 	(goal (goal-time ?rgt))
;//~ 	(test (> (- ?md ?t ?rgt 1) 0))
 =>
	(assert (exec (action inform) (param1 ?r) (param2 ?c) (param3 ok) (step ?i)))
	(assert (informed_rural (+ ?infrur 1)))
	(modify ?ka (informed ok))
)

;//~ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;//~ ;;;;;;; REGOLE PER VARIARE LE UTILITA' DELLE CELLE ;;;;;;;;
;//~ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defrule reduce-utility-visited
	(declare (salience 10))
	(local_perc (p 8) (r ?r) (c ?c))
	?ka <- (kagent_cell (pos-r ?r) (pos-c ?c) (visited true) (utility ?u&:(neq ?u -3)))
	(test(> ?u -3))
 =>
	(modify ?ka (utility -3))
)

(defrule reduce-utility-informed-flood
	(declare (salience 10))
	(local_perc (r ?r) (c ?c))
	?ka <- (kagent_cell (pos-r ?r) (pos-c ?c) (visited false) (utility ?u&:(neq ?u -1)) (informed flood))
	(test(> ?u -1))
 =>
	(modify ?ka (utility -1))
)

(defrule reduce-utility-informed-ok
	(declare (salience 10))
	(local_perc (r ?r) (c ?c))
	?ka <- (kagent_cell (pos-r ?r) (pos-c ?c) (visited false) (utility ?u&:(neq ?u -2)) (informed ok))
	(test(> ?u -2))
 =>
	(modify ?ka (utility -2))
)

(defrule reduce-utility-preciseful-informed
	(declare (salience 10))
	(local_perc (r ?r) (c ?c))
	?ka <- (kagent_cell (pos-r ?r) (pos-c ?c) (visited true) (utility ?u&:(neq ?u -10)) (informed initial-flood|severe-flood))
	(test(> ?u -10))
 =>
	(modify ?ka (utility -10))
)


;//~ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;//~ ;;;;;;; REGOLE PER CONTARE LE NEXT_CELL ;;;;;;;
;//~ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defrule counter-next-cell-p2
	(declare (salience 1))
	(status (step ?i))
	(local_perc (p 2) (r ?r2) (c ?c2) (checked no))
	(not(countedp2))
	(not(movement))
	(kagent_cell (pos-r ?r2) (pos-c ?c2)(type urban|rural|lake|gate))
	?ncc <- (next_cell_counter ?n)	
=>
	(retract ?ncc)
	(assert (next_cell_counter (+ ?n 1)))
	(assert(countedp2))
)
	
(defrule counter-next-cell-p4
	(declare (salience 1))
	(status (step ?i))
	(local_perc (p 4) (r ?r4) (c ?c4) (checked no))
	(not(countedp4))
	(not(movement))
	(kagent_cell (pos-r ?r4) (pos-c ?c4)(type urban|rural|lake|gate))
	?ncc <- (next_cell_counter ?n)	
=>
	(retract ?ncc)
	(assert (next_cell_counter (+ ?n 1)))
	(assert(countedp4))
)	
	
(defrule counter-next-cell-p6
	(declare (salience 1))
	(status (step ?i))
	(local_perc (p 6) (r ?r6) (c ?c6) (checked no))
	(not(countedp6))
	(not(movement))
	(kagent_cell (pos-r ?r6) (pos-c ?c6)(type urban|rural|lake|gate))
	?ncc <- (next_cell_counter ?n)	
=>
	(retract ?ncc)
	(assert (next_cell_counter (+ ?n 1)))
	(assert(countedp6))
)

;//~ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;//~ ;;;;;;;;;;;;;;;;;;; FASE DI CHECKING E MOVE;;;;;;;;;;;;;;;;
;//~ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defrule check-forward
	(checking)
	(not (planning))
	(not (movement))
	(status (step ?i) (time ?t))
	(kagent (direction ?dir))
	?lp <- (local_perc (p 2) (r ?r) (c ?c) (checked no))
	(not (kagent_cell (pos-r ?r) (pos-c ?c) (type hill|border)))
	(kagent_cell (pos-r ?r) (pos-c ?c) (utility ?u&:(neq ?u -99999)))	
	(not (next_cell (pos-r ?r) (pos-c ?c) (action go-forward)))
 =>	
	(modify ?lp (checked yes))
	(assert
		(planning)
		(next_cell (pos-r ?r) (pos-c ?c) (direction ?dir) (action go-forward) )
		(current_max_goal_utility ?r ?c ?dir -99999)
	)
)

(defrule move-forward
	(declare (salience -1))
	(checking)	
	(not (planning))
	?mov <- (movement)
	(status (step ?i))
	?p1 <- (local_perc (p 1))
	?p2 <- (local_perc (p 2))
	?p3 <- (local_perc (p 3))
	?p4 <- (local_perc (p 4))
	?p5 <- (local_perc (p 5))
	?p6 <- (local_perc (p 6))
	?p7 <- (local_perc (p 7))
	?p8 <- (local_perc (p 8))
	?p9 <- (local_perc (p 9))
	?nc <- (next_cell (action go-forward) (utility ?u&:(neq ?u -999990)) (safety safe))
 =>  
	(retract ?p1 ?p2 ?p3 ?p4 ?p5 ?p6 ?p7 ?p8 ?p9 ?nc ?mov)
	(assert (exec (action go-forward) (step ?i)))
)

(defrule check-right-north
	(checking)
	(not (planning))
	(not (movement))
	(status (step ?i) (time ?t))
	(kagent (direction north))
	?lp <- (local_perc (p 6) (r ?r) (c ?c) (checked no))
	(not (kagent_cell (pos-r ?r) (pos-c ?c) (type hill|border)))
	(kagent_cell (pos-r ?r) (pos-c ?c) (utility ?u&:(neq ?u -99999)))
	(not (next_cell (pos-r ?r) (pos-c ?c) (action go-right)))
=>	
	(modify ?lp (checked yes))
	(assert
		(planning)
		(next_cell (pos-r ?r) (pos-c ?c) (direction east) (action go-right) )
		(current_max_goal_utility ?r ?c east -99999)
	)
)

(defrule check-right-south
	(checking)
	(not (planning))
	(not (movement))
	(status (step ?i) (time ?t))
	(kagent (direction south))
	?lp <- (local_perc (p 6) (r ?r) (c ?c) (checked no))
	(not (kagent_cell (pos-r ?r) (pos-c ?c) (type hill|border)))
	(kagent_cell (pos-r ?r) (pos-c ?c) (utility ?u&:(neq ?u -99999)))
	(not (next_cell (pos-r ?r) (pos-c ?c) (action go-right)))

 =>	
	(modify ?lp (checked yes))
	(assert
		(planning)
		(next_cell (pos-r ?r) (pos-c ?c) (direction west) (action go-right))
		(current_max_goal_utility ?r ?c west -99999)
	)
)

(defrule check-right-east
	(checking)
	(not (planning))
	(not (movement))
	(status (step ?i) (time ?t))
	(kagent (direction east))
	?lp <- (local_perc (p 6) (r ?r) (c ?c) (checked no))
	(not (kagent_cell (pos-r ?r) (pos-c ?c) (type hill|border)))
	(kagent_cell (pos-r ?r) (pos-c ?c) (utility ?u&:(neq ?u -99999)))
	(not (next_cell (pos-r ?r) (pos-c ?c) (action go-right)))
 =>	
	(modify ?lp (checked yes))
	(assert
		(planning)
		(next_cell (pos-r ?r) (pos-c ?c) (direction south) (action go-right) )
		(current_max_goal_utility ?r ?c south -99999)
	)
)

(defrule check-right-west
	(checking)
	(not (planning))
	(not (movement))
	(status (step ?i) (time ?t))
	(kagent (direction west))
	?lp <- (local_perc (p 6) (r ?r) (c ?c) (checked no))
	(not (kagent_cell (pos-r ?r) (pos-c ?c) (type hill|border)))
	(kagent_cell (pos-r ?r) (pos-c ?c) (utility ?u&:(neq ?u -99999)))
	(not (next_cell (pos-r ?r) (pos-c ?c) (action go-right)))
 =>	
	(modify ?lp (checked yes))
	(assert
		(planning)
		(next_cell (pos-r ?r) (pos-c ?c) (direction north) (action go-right) )
		(current_max_goal_utility ?r ?c north -99999)
	)
)

(defrule move-right
	(declare (salience -1))
	(checking)
	(not (planning))
	?mov <- (movement)
	(status (step ?i))
	?p1 <- (local_perc (p 1))
	?p2 <- (local_perc (p 2))
	?p3 <- (local_perc (p 3))
	?p4 <- (local_perc (p 4))
	?p5 <- (local_perc (p 5))
	?p6 <- (local_perc (p 6))
	?p7 <- (local_perc (p 7))
	?p8 <- (local_perc (p 8))
	?p9 <- (local_perc (p 9))	
	?nc <- (next_cell (action go-right) (utility ?u&:(neq ?u -999990)) (safety safe)) 
 =>  
	(retract ?p1 ?p2 ?p3 ?p4 ?p5 ?p6 ?p7 ?p8 ?p9 ?nc ?mov)
	(assert (exec (action go-right) (step ?i)))
)

(defrule check-left-north
	(checking)
	(not (planning))
	(not (movement))
	(status (step ?i) (time ?t))
	(kagent (direction north))
	?lp <- (local_perc (p 4) (r ?r) (c ?c) (checked no))
	(not (kagent_cell (pos-r ?r) (pos-c ?c) (type hill|border)))
	(kagent_cell (pos-r ?r) (pos-c ?c) (utility ?u&:(neq ?u -99999)))
	(not (next_cell (pos-r ?r) (pos-c ?c) (action go-left)))
 =>	
	(modify ?lp (checked yes))
	(assert
		(planning)
		(next_cell (pos-r ?r) (pos-c ?c) (direction west) (action go-left) )
		(current_max_goal_utility ?r ?c west -99999)
	)
)

(defrule check-left-south
	(checking)
	(not (planning))
	(not (movement))
	(status (step ?i) (time ?t))
	(kagent (direction south))
	?lp <- (local_perc (p 4) (r ?r) (c ?c) (checked no))
	(not (kagent_cell (pos-r ?r) (pos-c ?c) (type hill|border)))
	(kagent_cell (pos-r ?r) (pos-c ?c) (utility ?u&:(neq ?u -99999)))
	(not (next_cell (pos-r ?r) (pos-c ?c) (action go-left)))
 =>	
	(modify ?lp (checked yes))
	(assert
		(planning)
		(next_cell (pos-r ?r) (pos-c ?c) (direction east) (action go-left) )
		(current_max_goal_utility ?r ?c east -99999)
	)
)

(defrule check-left-east
	(checking)
	(not (planning))
	(not (movement))
	(status (step ?i) (time ?t))
	(kagent (direction east))
	?lp <- (local_perc (p 4) (r ?r) (c ?c) (checked no))
	(not (kagent_cell (pos-r ?r) (pos-c ?c) (type hill|border)))
	(kagent_cell (pos-r ?r) (pos-c ?c) (utility ?u&:(neq ?u -99999)))
	(not (next_cell (pos-r ?r) (pos-c ?c) (action go-left)))
 =>	
	(modify ?lp (checked yes))
	(assert
		(planning)
		(next_cell (pos-r ?r) (pos-c ?c) (direction north) (action go-left) )
		(current_max_goal_utility ?r ?c north -99999)
	)
)

(defrule check-left-west
	(checking)
	(not (planning))
	(not (movement))
	(status (step ?i) (time ?t))
	(kagent (direction west))
	?lp <- (local_perc (p 4) (r ?r) (c ?c) (checked no))
	(not (kagent_cell (pos-r ?r) (pos-c ?c) (type hill|border)))
	(kagent_cell (pos-r ?r) (pos-c ?c) (utility ?u&:(neq ?u -99999)))
	(not (next_cell (pos-r ?r) (pos-c ?c) (action go-left)))
 =>	
	(modify ?lp (checked yes))
	(assert
		(planning)
		(next_cell (pos-r ?r) (pos-c ?c) (direction south) (action go-left) )
		(current_max_goal_utility ?r ?c south -99999)
	)
)

(defrule move-left
	(declare (salience -1))
	(checking)
	(not (planning))
	?mov <- (movement)
	(status (step ?i))
	?p1 <- (local_perc (p 1))
	?p2 <- (local_perc (p 2))
	?p3 <- (local_perc (p 3))
	?p4 <- (local_perc (p 4))
	?p5 <- (local_perc (p 5))
	?p6 <- (local_perc (p 6))
	?p7 <- (local_perc (p 7))
	?p8 <- (local_perc (p 8))
	?p9 <- (local_perc (p 9))	
	?nc <- (next_cell (action go-left) (utility ?u&:(neq ?u -999990)) (safety safe))
 => 
	(retract ?p1 ?p2 ?p3 ?p4 ?p5 ?p6 ?p7 ?p8 ?p9 ?nc ?mov)
	(assert (exec (action go-left) (step ?i)))
)

;//~ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;//~ ;;;;;;;;;;;;;;      FASE DI CLEAN COUNTED     ;;;;;;;;;;;;;
;//~ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defrule clean-countedp2
	(movement)
	?cp2 <- (countedp2)
=> 
	(retract ?cp2)
)

(defrule clean-countedp4
	(movement)
	?cp4 <- (countedp4)
=> 
	(retract ?cp4)
)

(defrule clean-countedp6
	(movement)
	?cp6 <- (countedp6)
=> 
	(retract ?cp6)
)

(defrule in-gate-done-0
	(declare (salience -99))
	(status (step 0))
 =>
	(assert (exec (action done) (step 0)))
)

(defrule in-gate-done-1
	(declare (salience -99))
	(status (step ?i))
 =>
	(assert (exec (action done) (step ?i)))
)

;//~ con questa regola mi sposto in planner per fare la pianificazione con A* a profondita' limitata
(defrule init-planner
	(planning)
=>
	(focus PLANNER)
)
